package com.kurumi.controller;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.kurumi.domain.ShandongHomepageExcelDTO;
import com.kurumi.domain.response.Result;
import com.kurumi.service.HomepagePdfService;
import com.kurumi.service.MedicalRecordDataManageService;
import com.kurumi.thread.GenerateHomePagePDFCallable;
import com.kurumi.thread.HomePageHandleCallable;
import com.kurumi.thread.HomePageSaveCallable;
import com.kurumi.util.ListSplitUtil;

/**
 * 山东省首页数据接口上报导出
 * 
 * @author liyutao
 *
 */
@Controller
@RequestMapping("/shandong")
public class HomepageShandongExportController {

	private static final Logger logger = LoggerFactory.getLogger(HomepageShandongExportController.class);

	
	@Autowired
	private MedicalRecordDataManageService medicalRecordDataManageService;
	
	@Autowired
	private HomepagePdfService homepagePdfService;
	
	
    /**
     * 首页模板位置
     */
    @Value("${homepage.pdf.template}")
    private String homepagePdfTemplate;

    /**
     * 首页pdf根路径
     */
    @Value("${homepage.pdf.basepath}")
    private String homepagePdfBasepath;
	
	
	/**
	 * 拆分首页接送数据为表结构
	 * @param startTime 出院时间:yyyy-MM-dd
	 * @param endTime 出院时间: yyyy-MM-dd
	 * @return
	 */
	@ResponseBody
	@GetMapping("/generateHomepagePdf")
	public String generateHomepagePdf(String startTime, String endTime) {
		// 查询相关的guid集合
		 List<String> guidList = medicalRecordDataManageService.getMediclJson(startTime+" 00:00:00",endTime+" 23:59:59");
		//List<String> guidList = new ArrayList<>();
		//guidList.add("0d172e87f94c4ce7b952b0c03a1c5c2c");
		/**
		 * 每次处理一千条数据
		 */
		List<List<String>> lists = ListSplitUtil.split(guidList, 1000);
		
		int count = 0;
		
		// 去调用写入,根据数据库分页的总的页数来
		for (List<String> subGuidList : lists) {
			try {
				Integer handleCount = homepagePdfCallable(subGuidList);
				count+=handleCount;
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ExecutionException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return "处理数据条数为:"+count;
	}
	
	
	/**
	 * 拆分首页接送数据为表结构
	 * @param startTime 出院时间:yyyy-MM-dd
	 * @param endTime 出院时间: yyyy-MM-dd
	 * @return
	 */
	@ResponseBody
	@GetMapping("/handleHomepageDataByOnlyIds")
	public String handleHomepageDataByOnlyIds(String onlyIds) {
		// 查询相关的guid集合
		//List<String> guidList = medicalRecordDataManageService.getMediclJson(startTime+" 00:00:00",endTime+" 23:59:59");
		//List<String> guidList = medicalRecordDataManageService.syncMediclRecordBasicVisitGuid("2022-06-01","2022-06-30");
		
		if(onlyIds==null || onlyIds.equals("")) {
			return "参数onlyIds不可为空!";
		}
		List<String> guidList = medicalRecordDataManageService.getVisitGuidByOnlyIds(onlyIds);
		
//		 List<String> guidList = new ArrayList<>();
//		 guidList.add("6980367c6bfe4f0791fbc09987ee110a");
//		 guidList.add("12e8a9f44b8f47d59084ff937c15cf6e");
//		 guidList.add("4ff13b5d8e7f4a8c8be97e16fea50876");
//		 guidList.add("0a5665c9f2d141fab0c14b965bbbf472");
//		 guidList.add("b798f5c2b1754ba589c57a5b92c18b99");
//		 guidList.add("0a6905bf5a3a43df8055fadbd4e11596");
//		 guidList.add("e2f49d9a78aa45faa5080cbff640d22c");
//		 guidList.add("6716fc864905404585a9a3c2a3a1d16a");
		/**
		 * 每次处理一千条数据
		 */
		List<List<String>> lists = ListSplitUtil.split(guidList, 1000);
		
		int count = 0;
		
		// 去调用写入,根据数据库分页的总的页数来
		for (List<String> subGuidList : lists) {
			try {
				
				Integer handleCount = homepageCallable(subGuidList);
				count+=handleCount;
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ExecutionException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return "处理数据条数为:"+guidList.size();
	}
	
	
	/**
	 * 拆分首页接送数据为表结构
	 * @param startTime 出院时间:yyyy-MM-dd
	 * @param endTime 出院时间: yyyy-MM-dd
	 * @return
	 */
	@ResponseBody
	@GetMapping("/handleHomepageData")
	public String handleHomepageData(String startTime, String endTime) {
		// 查询相关的guid集合
		List<String> guidList = medicalRecordDataManageService.getMediclJson(startTime+" 00:00:00",endTime+" 23:59:59");
		//List<String> guidList = medicalRecordDataManageService.syncMediclRecordBasicVisitGuid("2022-06-01","2022-06-30");
//		 List<String> guidList = new ArrayList<>();
//		 guidList.add("6980367c6bfe4f0791fbc09987ee110a");
//		 guidList.add("12e8a9f44b8f47d59084ff937c15cf6e");
//		 guidList.add("4ff13b5d8e7f4a8c8be97e16fea50876");
//		 guidList.add("0a5665c9f2d141fab0c14b965bbbf472");
//		 guidList.add("b798f5c2b1754ba589c57a5b92c18b99");
//		 guidList.add("0a6905bf5a3a43df8055fadbd4e11596");
//		 guidList.add("e2f49d9a78aa45faa5080cbff640d22c");
//		 guidList.add("6716fc864905404585a9a3c2a3a1d16a");
		/**
		 * 每次处理一千条数据
		 */
		List<List<String>> lists = ListSplitUtil.split(guidList, 1000);
		
		int count = 0;
		
		// 去调用写入,根据数据库分页的总的页数来
		for (List<String> subGuidList : lists) {
			try {
				
				Integer handleCount = homepageCallable(subGuidList);
				count+=handleCount;
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ExecutionException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return "处理数据条数为:"+count;
	}
	
	
	/**
	 * 导出卫统数据信息
	 * @param response
	 * @param startTime
	 * @param endTime
	 * @throws InterruptedException
	 */
	@ResponseBody
	@RequestMapping("/exportExcel")
	public void exportExcel(HttpServletResponse response,String startTime,String endTime) throws InterruptedException {
		ExcelWriter excelWriter = null;
		try (
			ServletOutputStream out = response.getOutputStream()) {
			// 设置字符集为utf-8
			response.setCharacterEncoding("utf8");
			response.setContentType("application/vnd.ms-excel;charset=utf-8");
			// 通知浏览器服务器发送的数据格式
			response.setHeader("Content-Disposition",
					"attachment; filename=" + URLEncoder.encode("卫统首页2021版" + ".xlsx", "UTF-8"));
			// 发送一个报头，告诉浏览器当前页面不进行缓存，每次访问的时间必须从服务器上读取最新的数据
			response.setHeader("Cache-Control", "no-store");
			response.addHeader("Cache-Control", "max-age=0");
			// 这里 需要指定写用哪个class去写
			excelWriter = EasyExcel.write(out, ShandongHomepageExcelDTO.class).build();
			// 这里注意 如果同一个sheet只要创建一次
			WriteSheet writeSheet = EasyExcel.writerSheet("sheet").build();
			
			// 查询相关的guid集合
			List<String> guidList = medicalRecordDataManageService.getMediclJson(startTime+" 00:00:00",endTime+" 23:59:59");
//			List<String> guidList = new ArrayList<>();
//			guidList.add("51fae0f4f1ad4deba5a5c6c37323c545");
//			guidList.add("a1539108fabb4957a66145c5a535e51f");
//			guidList.add("be5e55f5db804602918cba4782f117ff");
//			guidList.add("12e99a31bbfa44efb2f4f70a25f995f6");
//			guidList.add("be5e55f5db804602918cba4782f117ff");
//			guidList.add("cc530340fe1c4636b4df4820e006c3b8");
			
			
			
			
			
			
			/**
			 * 每次处理一千条数据
			 */
			List<List<String>> lists = ListSplitUtil.split(guidList, 1000);
			
			
			// 去调用写入,根据数据库分页的总的页数来
			for (List<String> subGuidList : lists) {
				// 处理数据并导出
				try {
					excelWriter.write(handleDate(subGuidList), writeSheet);
				}catch (Exception e) {
					e.printStackTrace();
				}
				
			
			}
			// 千万别忘记finish 会帮忙关闭流
			excelWriter.finish();
			out.flush();
		} catch (IOException e) {
			throw new RuntimeException();
		}

	}
	
	
	/**
	 * 处理导出excel数据
	 * @param subGuidList 处理guid集合
	 * @throws Execution
	 */
	private List<ShandongHomepageExcelDTO> handleDate(List<String> subGuidList) throws InterruptedException, ExecutionException {
		
		List<ShandongHomepageExcelDTO> handleDataList = new ArrayList<>();
		// 默认5个线程
		int threadNum = 5;
		
		logger.info("处理数据条数为{}条"+subGuidList.size());
		
		/**
		 * 多线程分析数据
		 */
		List<Future<List<ShandongHomepageExcelDTO>>> list = new ArrayList<>();
		ExecutorService executor = Executors.newFixedThreadPool(threadNum);
		// 计算分组数量
		int num = (subGuidList.size() / threadNum) + 1;
		// 将数据分组
		List<List<String>> guidLists = ListSplitUtil.split(subGuidList, num);
		 // 计算每个线程需要处理的记录数
		for (List<String> guids : guidLists) {
			
			// 添加任务
			Callable<List<ShandongHomepageExcelDTO>> task = new HomePageHandleCallable(guids,medicalRecordDataManageService);
			Future<List<ShandongHomepageExcelDTO>> f = executor.submit(task);
			// 接受返回结果
			list.add(f);
		}
		// 关闭线程池
		executor.shutdown();
		for (Future<List<ShandongHomepageExcelDTO>> future : list) {
			// 从Future对象上获取任务的返回值，并输出到控制台
			List<ShandongHomepageExcelDTO> returnDataList = future.get();
			//logger.info("当前线程处理数据数量为{}",returnDataList.size());
			handleDataList.addAll(returnDataList);
		}
		
		logger.info("处理后数据数量为:{}",handleDataList.size());
		return handleDataList;
	}
	
	
	/**
	 * 处理导出excel数据
	 * @param subGuidList 处理guid集合
	 * @throws Execution
	 */
	private Integer homepageCallable(List<String> subGuidList) throws InterruptedException, ExecutionException {
		
		Integer handleDataCount = 0;
		// 默认5个线程
		int threadNum = 5;
		
		logger.info("处理数据条数为{}条"+subGuidList.size());
		
		/**
		 * 多线程分析数据
		 */
		List<Future<Integer>> list = new ArrayList<>();
		ExecutorService executor = Executors.newFixedThreadPool(threadNum);
		// 计算分组数量
		int num = (subGuidList.size() / threadNum) + 1;
		// 将数据分组
		List<List<String>> guidLists = ListSplitUtil.split(subGuidList, num);
		 // 计算每个线程需要处理的记录数
		for (List<String> guids : guidLists) {
			
			// 添加任务
			Callable<Integer> task = new HomePageSaveCallable(guids,medicalRecordDataManageService);
			Future<Integer> f = executor.submit(task);
			// 接受返回结果
			list.add(f);
		}
		// 关闭线程池
		executor.shutdown();
		for (Future<Integer> future : list) {
			// 从Future对象上获取任务的返回值，并输出到控制台
			Integer returnDataCount = future.get();
			logger.info("当前线程处理数据数量为{}",returnDataCount);
			handleDataCount+=returnDataCount;
		}
		
		logger.info("处理后数据数量为:{}",handleDataCount);
		return handleDataCount;
	}
	
	
	/**
	 * 处理导出pdf数据
	 * @param subGuidList 处理guid集合
	 * @throws Execution
	 */
	private Integer homepagePdfCallable(List<String> subGuidList) throws InterruptedException, ExecutionException {
		
		Integer handleDataCount = 0;
		// 默认5个线程
		int threadNum = 5;
		
		logger.info("处理数据条数为{}条"+subGuidList.size());
		
		/**
		 * 多线程分析数据
		 */
		List<Future<Integer>> list = new ArrayList<>();
		ExecutorService executor = Executors.newFixedThreadPool(threadNum);
		// 计算分组数量
		int num = (subGuidList.size() / threadNum) + 1;
		// 将数据分组
		List<List<String>> guidLists = ListSplitUtil.split(subGuidList, num);
		 // 计算每个线程需要处理的记录数
		for (List<String> guids : guidLists) {
			
			// 添加任务
			Callable<Integer> task = new GenerateHomePagePDFCallable(guids,medicalRecordDataManageService,homepagePdfTemplate,homepagePdfBasepath);
			Future<Integer> f = executor.submit(task);
			// 接受返回结果
			list.add(f);
		}
		// 关闭线程池
		executor.shutdown();
		for (Future<Integer> future : list) {
			// 从Future对象上获取任务的返回值，并输出到控制台
			Integer returnDataCount = future.get();
			logger.info("当前线程处理数据数量为{}",returnDataCount);
			handleDataCount+=returnDataCount;
		}
		
		logger.info("处理后数据数量为:{}",handleDataCount);
		return handleDataCount;
	}
	
	
	@GetMapping("/showHomepagePdfPage")
	public ModelAndView showHomepagePdfPage(String visitGuid, HttpServletRequest request,HttpServletResponse response) {
		Map<String,String> model = new HashMap<>();
		model.put("visitGuid",visitGuid);
		return new ModelAndView("searching/showHomepagePdfPage",model);
	}
	
	
	@ResponseBody
	@RequestMapping("/generateHomepagePDF")
	public Result generateHomepagePDF(String visitGuid) {
		try {
			String pdfBase64 = homepagePdfService.generateHomepagePdf(visitGuid);
			return new Result(true,"生成PDF成功!",pdfBase64);
		}catch(Exception e) {
			e.printStackTrace();
			return new Result(false,"生成pdf文件失败,异常信息:"+e.getMessage());
		}
	}
	

}
